/*******************************************************************************
* File Name: CSD_Touchpad_TMG.c
* Version 1.10
*
* Description:
*  This file provides the source code of the API for the CapSense TMG component.
*
********************************************************************************
* Copyright 2014, Cypress Semiconductor Corporation.  All rights reserved.
* You may use this file only in accordance with the license, terms, conditions,
* disclaimers, and limitations in the end user license agreement accompanying
* the software package with which this file was provided.
*******************************************************************************/

#include "CSD_Touchpad_TMG.h"


static void CSD_Touchpad_TMG_SysTickISR(void);
uint32      CSD_Touchpad_TMG_currentTimestamp;
uint16 CSD_Touchpad_TMG_edgeSwipeCompleteTimeout = CSD_Touchpad_TMG_EDGE_SWIPE_COMPLETE_TIMEOUT;

/*******************************************************************************
* Function Name: CSD_Touchpad_TMG_TimerEnableInt
********************************************************************************
*
* Summary:
*  Enables Systick timer interrupts and configures the SystemTick timer callback
*  slot to the component function that updates the timestamp value.
*
* Parameters:
*  None
*
* Return:
*  Status
*     Value               Description
*    CYRET_SUCCESS       Successful
*    CYRET_INVALID_STATE Failure - no free callback slot was found
*
* Side Effects:
*  This function reinitialises the System Tick timer settings and callbacks so
*  that all the settings applied to the System Tick timer except for
*  the callback table will be lost and default parameters will be set.
*
*******************************************************************************/
cystatus CSD_Touchpad_TMG_TimerEnableInt(void)
{
    uint32 i;
    cySysTickCallback sysTickCallbacks[CY_SYS_SYST_NUM_OF_CALLBACKS];
    cySysTickCallback sysTickCallbackAddress;
    cystatus retValue = CYRET_INVALID_STATE;

    for (i = 0u; i < CY_SYS_SYST_NUM_OF_CALLBACKS; i++)
    {
        sysTickCallbacks[i] = (void *) 0;
    }

    CSD_Touchpad_TMG_currentTimestamp = 0u;

    /* If SysTick timer wasn't configured */
    if (CySysTickInitVar == 0u)
    {
        /* SysTick timer seems to be not configured.
         * Configure SysTick timer and set callback.
         */
        CySysTickStart();
        (void)CySysTickSetCallback(0u, &CSD_Touchpad_TMG_SysTickISR);
        retValue = CYRET_SUCCESS;
    }
    else
    {
        /* If SysTick timer was configured save user callbacks */
        for (i = 0u; i < CY_SYS_SYST_NUM_OF_CALLBACKS; i++)
        {
            sysTickCallbackAddress = CySysTickGetCallback(i);

            /* Make sure that callback slot is used */
            if (sysTickCallbackAddress != (void *) 0 )
            {
                /* Save address if it wasn't set by this component */
                if (sysTickCallbackAddress != &CSD_Touchpad_TMG_SysTickISR)
                {
                    sysTickCallbacks[i] = sysTickCallbackAddress;
                }
                else
                {
                    /* In case there already is one callback from CSD_Touchpad_TMG*/
                    retValue = CYRET_SUCCESS;
                }
            }
            else if (CYRET_SUCCESS != retValue)
            {
                /* If there was a free callback slot - use it */
                sysTickCallbacks[i] = &CSD_Touchpad_TMG_SysTickISR;
                retValue = CYRET_SUCCESS;
            }
            else
            {
                /* Skip empty slot if we already added one for component */
            }
        }

        if (CYRET_SUCCESS == retValue)
        {
            /* Reset System Tick timer configuration */
            CySysTickInitVar = 0u;
            CySysTickStart();

            /* Restore user callbacks if any and set own callback */
            for (i = 0u; i < CY_SYS_SYST_NUM_OF_CALLBACKS; i++)
            {
                (void)CySysTickSetCallback(i, sysTickCallbacks[i]);
            }
        }
    }

    return (retValue);
}


/*******************************************************************************
* Function Name: CSD_Touchpad_TMG_TimerDisableInt
********************************************************************************
*
* Summary:
*  Disables Systick timer interrupts.
*
* Parameters:
*  None
*
* Return:
*  None
*
* Side Effects:
*  Stops the SysTick timer if there are no active callback slots left and
*  disables SysTick interrupt.
*
*******************************************************************************/
void CSD_Touchpad_TMG_TimerDisableInt(void)
{
    uint32 i;
    uint32 nullPointers = 0u;


    /* Find used callback slot */
    for (i = 0u; i < CY_SYS_SYST_NUM_OF_CALLBACKS; i++)
    {
        if (CySysTickGetCallback(i) == &CSD_Touchpad_TMG_SysTickISR)
        {
            /* Free callback */
            (void)CySysTickSetCallback(i, (void *) 0 );
            nullPointers++;
        }
        else if (CySysTickGetCallback(i) == (void *) 0 )
        {
            /* This callback slot is unused */
            nullPointers++;
        }
        else
        {
            /* This callback slot is used by some function */
        }
    }

    if (nullPointers == CY_SYS_SYST_NUM_OF_CALLBACKS)
    {
        /* If there are no used callback slots - disable SysTick timer */
        CySysTickDisableInterrupt();
        CySysTickStop();
    }
}


/*******************************************************************************
* Function Name: CSD_Touchpad_TMG_DecodeAllGestures
********************************************************************************
*
* Summary:
*  Decodes all enabled gestures in the customizer and returns the detected
*  gesture code.
*  CSD_Touchpad_TMG_InitGestures and CSD_Touchpad_TMG_TimerEnableInt has to be
*  called once prior calling this or any other API for gesture decoding.
*
* Parameters:
*  touchNumber: Number of fingers on the trackpad. Valid range 0-2.
*  pos: Pointer to structure with coordinates of touches.
*
* Return:
*  Detected gesture code.
*
*******************************************************************************/
uint32 CSD_Touchpad_TMG_DecodeAllGestures(uint32 touchNumber, const CSD_Touchpad_TMG_POSITION_STRUCT *pos)
{
    uint32 gestureID = CSD_Touchpad_TMG_NO_GESTURE;

    /* Variable for detected click gestures */
    uint32 clickGesture = CSD_Touchpad_TMG_NO_GESTURE;

    /* Variable for detected single touch gestures */
    uint32 stGesture = CSD_Touchpad_TMG_NO_GESTURE;

    /* Variable for detected double touch gestures */
    uint32 dtGesture = CSD_Touchpad_TMG_NO_GESTURE;

    #if (CSD_Touchpad_TMG_ROTATE_ENABLED != 0u)
        static uint32 rotationActive = 0u;
    #endif /* (CSD_Touchpad_TMG_ROTATE_ENABLED != 0u) */

	#if (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u)
		static uint32 edgeTimeoutStamp = 0u;
		uint32 deltaTimeoutStamp = 0u;
    #endif /* (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u) */
	
    #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) ||\
                                                         (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                         (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u)))
        static uint32 edgeSwipeActive = 0u;
    #endif /* ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) ||\
                                                               (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                               (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u))) */

    #if ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) && ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) ||\
                                                     (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                     (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u)))
        static uint32 clickAndDragActive = 0u;
    #endif /* ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) && ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) ||\
                                                           (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                           (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u))) */

    #if (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u)
        uint32 edgeSwipeGesture = CSD_Touchpad_TMG_NO_GESTURE;
    #endif /* (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) */

	#if ((CSD_Touchpad_TMG_CLICKS_ENABLED != 0u) || (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u))
		clickGesture = Gesture_DecodeAllClickGestures((uint8)touchNumber, CSD_Touchpad_TMG_currentTimestamp, pos);
	#endif /* ((CSD_Touchpad_TMG_CLICKS_ENABLED != 0u) || (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u)) */
	
    #if (CSD_Touchpad_TMG_CLICKS_ENABLED != 0u)
		gestureID = clickGesture;
        #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) || (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u))
        if (clickGesture == CSD_Touchpad_TMG_CLICK_AND_DRAG)
        {
            clickAndDragActive = 1u;
        }
        #endif /* ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) || (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u)) */
    #endif /* (CSD_Touchpad_TMG_CLICKS_ENABLED != 0u) */

    #if (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u)
        stGesture = Gesture_DecodeSTRotateGestures((uint8)touchNumber, CSD_Touchpad_TMG_currentTimestamp, pos);

        #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) || (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u))
            #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u))
                if ((clickAndDragActive == 1) || (edgeSwipeActive == 1u))
            #elif (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u)
                if (clickAndDragActive == 1)
            #elif (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u)
                if (edgeSwipeActive == 1u)
            #endif /* ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u)) */
            {
                stGesture = CSD_Touchpad_TMG_NO_GESTURE;
            }
        #endif /* ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) || (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u)) */
        if ((stGesture == CSD_Touchpad_TMG_ROTATE_CW) || (stGesture == CSD_Touchpad_TMG_ROTATE_CCW))
        {
            rotationActive = CSD_Touchpad_TMG_ROTATE_TO_OTHER_DEBOUNCE;
        }
        else
        {
            if (rotationActive > 0u)
            {
                rotationActive--;
            }
        }

        if (((stGesture == CSD_Touchpad_TMG_NO_GESTURE)||(stGesture == CSD_Touchpad_TMG_TOUCHDOWN) \
                                        ||(stGesture == CSD_Touchpad_TMG_LIFT_OFF))&&(rotationActive == 0u))
    #else
        if ((stGesture == CSD_Touchpad_TMG_NO_GESTURE)||(stGesture == CSD_Touchpad_TMG_TOUCHDOWN) \
                                        ||(stGesture == CSD_Touchpad_TMG_LIFT_OFF))
    #endif /* (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u) */
    {
        #if (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u)
            #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u))
                if ((clickAndDragActive == 0u)&&(edgeSwipeActive == 0u))
            #elif (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u)
                if (clickAndDragActive == 0u)
            #elif (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u)
                if (edgeSwipeActive == 0u)
            #else
                if (1u == 1u)
            #endif /* ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && (CSD_Touchpad_TMG_CLICKS_ENABLED == 1u)) */
            {
                stGesture = Gesture_DecodeSTScrollGestures((uint8)touchNumber, CSD_Touchpad_TMG_currentTimestamp, pos);
            }
        #elif (CSD_Touchpad_TMG_FLICKS_ENABLED == 1u)
            stGesture = Gesture_DecodeFlickGestures((uint8)touchNumber, CSD_Touchpad_TMG_currentTimestamp, pos);
        #endif /* (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) */
    }

    #if (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u)
        edgeSwipeGesture = Gesture_DecodeEdgeSwipeGestures((uint8)touchNumber, CSD_Touchpad_TMG_currentTimestamp, pos);

        #if (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u)
            if (((edgeSwipeGesture != CSD_Touchpad_TMG_NO_GESTURE) && \
                (edgeSwipeGesture != CSD_Touchpad_TMG_TOUCHDOWN) && (edgeSwipeGesture != CSD_Touchpad_TMG_LIFT_OFF)) \
                                                                                        && (rotationActive == 0u))
        #else
            if ((edgeSwipeGesture != CSD_Touchpad_TMG_NO_GESTURE) && \
                (edgeSwipeGesture != CSD_Touchpad_TMG_TOUCHDOWN) && (edgeSwipeGesture != CSD_Touchpad_TMG_LIFT_OFF))
        #endif /* (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u) */
        {
            stGesture = edgeSwipeGesture;
            #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) ||\
                                                                 (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                                 (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u)))
                edgeSwipeActive = 1u;
            #endif /* ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) ||\
                                                                       (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                                       (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u))) */
        }
    #endif /* (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) */

    if ((stGesture != CSD_Touchpad_TMG_NO_GESTURE)&&(stGesture != CSD_Touchpad_TMG_TOUCHDOWN) \
                                        &&(stGesture != CSD_Touchpad_TMG_LIFT_OFF))
    {
        gestureID = stGesture;
    }
    else if ((clickGesture == CSD_Touchpad_TMG_TOUCHDOWN) || (clickGesture == CSD_Touchpad_TMG_LIFT_OFF))
    {
        gestureID = clickGesture;
    }
    else
    {
        /* Do not change gestureID */
    }

    dtGesture = CSD_Touchpad_TMG_DecodeZoomGestures(touchNumber, pos);
    if ((dtGesture == CSD_Touchpad_TMG_NO_GESTURE) || (dtGesture == CSD_Touchpad_TMG_TOUCHDOWN) \
                                        || (dtGesture == CSD_Touchpad_TMG_LIFT_OFF))
    {
        dtGesture = CSD_Touchpad_TMG_DecodeDTScrollGestures(touchNumber, pos);
    }
    else
    {
        (void)CSD_Touchpad_TMG_DecodeDTScrollGestures(touchNumber, pos);
    }

    if ((dtGesture != CSD_Touchpad_TMG_NO_GESTURE) && (dtGesture != CSD_Touchpad_TMG_TOUCHDOWN) \
                                        && (dtGesture != CSD_Touchpad_TMG_LIFT_OFF))
    {
        gestureID = dtGesture;
    }
	
	#if (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u)
		if((gestureID >= CSD_Touchpad_TMG_EDGE_SWIPE_LEFT)&&(gestureID <= CSD_Touchpad_TMG_EDGE_SWIPE_BOTTOM))
		{
			edgeTimeoutStamp = CSD_Touchpad_TMG_currentTimestamp;
		}
    #endif /* (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u) */

    if ((clickGesture == CSD_Touchpad_TMG_LIFT_OFF) || (clickGesture == CSD_Touchpad_TMG_TOUCHDOWN) || \
            (gestureID == CSD_Touchpad_TMG_NO_GESTURE))
    {
        #if ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) && ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) ||\
                                                         (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                         (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u)))
			if(0u != clickAndDragActive)
			{
				clickAndDragActive = 0u;
			}
        #endif /* ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) && ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) ||\
                                                               (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u) ||\
                                                               (CSD_Touchpad_TMG_ROTATE_ENABLED == 1u))) */
        
		#if (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u)
		deltaTimeoutStamp = CSD_Touchpad_TMG_currentTimestamp - edgeTimeoutStamp;
        if ((clickGesture == CSD_Touchpad_TMG_LIFT_OFF) || (deltaTimeoutStamp >= (CSD_Touchpad_TMG_edgeSwipeCompleteTimeout)))
        {
		    edgeTimeoutStamp = 0u;
            #if ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) || \
                                                                        (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u)))
				if(0u != edgeSwipeActive)
				{
					edgeSwipeActive = 0u;
				}
				
            #endif /* ((CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED == 1u) && ((CSD_Touchpad_TMG_CLICKS_ENABLED == 1u) || \
                                                                        (CSD_Touchpad_TMG_ST_SCROLLS_ENABLED == 1u))) */
        }
		#endif /* (CSD_Touchpad_TMG_EDGE_SWIPE_ENABLED != 0u) */
    }

    return (gestureID);
}


/*******************************************************************************
* Function Name: CSD_Touchpad_TMG_SysTickISR
********************************************************************************
*
* Summary:
*  Interrupt routine for System Tick Timer
*
* Parameters:
*  None
*
* Return:
*  None
*
*******************************************************************************/
static void CSD_Touchpad_TMG_SysTickISR(void)
{
    CSD_Touchpad_TMG_currentTimestamp++;
}


/*******************************************************************************
* Function Name: CSD_Touchpad_TMG_ballisticsMultiplier
********************************************************************************
*
* Summary:
*  This API is to run the ballistic Multiplier.
*  CSD_Touchpad_TMG_TimerEnableInt has to be called once prior calling this API.
*
* Parameters:
*   ballisticMultiplier: Pointer to the structure which contains API parameters.
*   pos: Pointer to dX and dY coordinates.
*
* Return:
*  None
*
* Global Variables:
*  None
*
*******************************************************************************/
void CSD_Touchpad_TMG_BallisticsMultiplier(const CSD_Touchpad_TMG_BALLISTIC_MULT * ballisticMultiplier, int16 *pos)
{
    #if (CSD_Touchpad_TMG_BALLISTICS_ENABLED == 1u)
        CSD_Touchpad_TMG_BALLISTIC_MULT_INT ballisticsStrct;
        ballisticsStrct.paramStr = *ballisticMultiplier;
        ballisticsStrct.currentTimestamp = CSD_Touchpad_TMG_GetTimerGlobalCounter();
        BallisticMultiplier_TMG_v1_00(&ballisticsStrct, pos);
    #endif /* (CSD_Touchpad_TMG_BALLISTICS_ENABLED == 1u) */
}


/* [] END OF FILE */
